//
// This code is to be used for evaluation of the CS2J tool ONLY.
//
// This file was translated from C# to Java by CS2J (http://www.cs2j.com).
//
// For more information about CS2J please contact info@twigletsoftware.com
//
// Translated by CS2J (http://www.cs2j.com): 2013/1/12 14:27:19
//

package ms.sudoku;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import ms.sudoku.technique.BeginnerTechnique;
import ms.sudoku.technique.BlockAndColumnRowInteractionTechnique;
import ms.sudoku.technique.EliminationTechnique;
import ms.sudoku.technique.HiddenPairTechnique;
import ms.sudoku.technique.HiddenQuadTechnique;
import ms.sudoku.technique.HiddenSingleTechnique;
import ms.sudoku.technique.HiddenTripletTechnique;
import ms.sudoku.technique.NakedPairTechnique;
import ms.sudoku.technique.NakedQuadTechnique;
import ms.sudoku.technique.NakedSingleTechnique;
import ms.sudoku.technique.NakedTripletTechnique;
import ms.sudoku.technique.XwingTechnique;

import common.Difficulty;

//Description: Configuration options for the puzzle generator.
public final class GeneratorOptions {
	// Perceived difficulty of the puzzle.
	private Difficulty difficulty = Difficulty.Easy;

	// The minimum number of filled cells in the generated puzzle.
	private int minFilledCells;

	// The size of the puzzle to be generated.
	private int boxSize;

	// The maximum number of times brute-force techniques can be used in solving
	// the puzzle.
	private int maxDecisionPoints = 0;

	// The number of puzzles to generate in order to pick the best of the lot.
	private int puzzlesCount;

	// Techniques allowed to be used in the generation of puzzles.
	private List<EliminationTechnique> allowedTechniques;

	// Whether only symmetrical puzzles should be generated.
	private boolean ensureSymmetry;

	public static GeneratorOptions create(Difficulty difficultyLevel) {
		switch (difficultyLevel) {
		case Easy:
			return new GeneratorOptions(3, Difficulty.Easy, 32, 0, 3,
					new EliminationTechnique[] { new BeginnerTechnique() }, true);
		case Medium:
			return new GeneratorOptions(3, Difficulty.Medium, 33, 0, 10, new EliminationTechnique[] {
					new BeginnerTechnique(), new NakedSingleTechnique(), new HiddenSingleTechnique(),
					new BlockAndColumnRowInteractionTechnique(), new NakedPairTechnique(), new HiddenPairTechnique(),
					new NakedTripletTechnique() }, true);
		case Hard:
			return new GeneratorOptions(3, Difficulty.Hard, 0, 0, 20, new EliminationTechnique[] {
					new BeginnerTechnique(), new NakedSingleTechnique(), new HiddenSingleTechnique(),
					new BlockAndColumnRowInteractionTechnique(), new NakedPairTechnique(), new HiddenPairTechnique(),
					new NakedTripletTechnique(), new HiddenTripletTechnique(), new NakedQuadTechnique(),
					new HiddenQuadTechnique(), new XwingTechnique() }, true);
		default:
			throw new RuntimeException("difficultyLevel");

		}
	}

	public GeneratorOptions(int size, Difficulty difficulty, int minimumFilledCells, int maximumNumberOfDecisionPoints,
			int numberOfPuzzles, EliminationTechnique[] techniques, boolean ensureSymmetry) {
		if (size != 3)
			throw new RuntimeException("size");

		if (false == difficulty.isValid())
			throw new RuntimeException("difficulty");

		if (minimumFilledCells < 0)
			throw new RuntimeException("minimumFilledCells");

		if (numberOfPuzzles < 1)
			throw new RuntimeException("numberOfPuzzles");

		if (techniques == null)
			throw new RuntimeException("techniques");

		this.difficulty = difficulty;
		this.boxSize = size;
		this.minFilledCells = minimumFilledCells;
		this.maxDecisionPoints = maximumNumberOfDecisionPoints;
		this.puzzlesCount = numberOfPuzzles;
		this.ensureSymmetry = ensureSymmetry;
		this.allowedTechniques = new ArrayList<>(Arrays.asList(techniques));
	}

	public int getMinFilledCells() {
		return minFilledCells;
	}

	public int getBoxSize() {
		return boxSize;
	}

	public int getDecisionPoints() {
		return maxDecisionPoints;
	}

	public int getPuzzlesCount() {
		return puzzlesCount;
	}

	public List<EliminationTechnique> getAllowedTechniques() {
		return allowedTechniques;
	}

	public boolean getEnsureSymmetry() {
		return ensureSymmetry;
	}

	public void setEnsureSymmetry(boolean value) {
		ensureSymmetry = value;
	}

	public Difficulty getDifficulty() {
		return difficulty;
	}

}
